package com.fliangyun.nsa.nsamanage.utils;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.imageio.IIOImage;
import javax.imageio.ImageIO;
import javax.imageio.ImageWriteParam;
import javax.imageio.ImageWriter;
import javax.swing.*;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.awt.image.ColorModel;
import java.awt.image.ConvolveOp;
import java.awt.image.Kernel;
import java.io.ByteArrayOutputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.MalformedURLException;
import java.util.Iterator;


/**
 * @author zhao
 * @date 2020/8/31 16:11
 */
public class ImageIoUtil {

	private static Logger logger = LoggerFactory.getLogger(ImageIoUtil.class);

	private final static String jpg = "jpg";
	private final static String jpeg = "jpeg";


//	public static void main(String[] args) {
//		String url = "E:\\easypower\\userfiles\\certificate\\userCertificate\\22.jpg";
//		String url2 = "E:\\easypower\\userfiles\\certificate\\userCertificate\\22.jpg";
//		String suffix = url .substring(url.lastIndexOf(".") + 1);
//		compression(url, url2,1.5,0.1f,0.5f,suffix);
//	}

	/***
	 *
	 * @author zhao
	 * @date 2020/9/3 10:19
	 * @param source 图片地址
	 * @param num  分辨率缩放比例，取值范围大于1
	 * @param quality  图片质量缩放比例，取值范围大于0小于1
	 * @param softenFactor  图片软化比例，取值范围大于0，小于1，小于0.1时，图片大小增加
	 * @param suffix 图片后缀名
	 * @return byte[]
	 */
	public static byte[] compression(String source, String target, double num, float softenFactor,
									 float quality, String suffix) {
		try {

			boolean numFlag = !"".equals(num) && num > 1;
			boolean softenFactorFlag = !"".equals(softenFactor)
					&& softenFactor > 0 && softenFactor < 1;
			boolean qualityFlag = !"".equals(quality)
					&& quality > 0 && quality < 1;
			//判断是否是jpeg或者jpg图片，其他类型不支持质量压缩，至少我没找到方法
			boolean suffixFlag = jpeg.equals(suffix) || jpg.equals(suffix);

			// 描述请见 <注解1>
			Image temp = new ImageIcon(source).getImage();

			int w = temp.getWidth(null);
			int h = temp.getHeight(null);

			if (numFlag) {
				//分辨率压缩的后的大小
				h = new Double(h / num).intValue();
				w = new Double(w / num).intValue();
			}

			// 分辨率压缩
			BufferedImage bimage = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);

			// 将图像复制到缓冲的图像。
			Graphics g = bimage.createGraphics();
			g.drawImage(temp, 0, 0, w, h, Color.LIGHT_GRAY, null);
			g.dispose();

			//如果三个值都不符合取值范围，则不进行压缩
			//其实ImageIo在write时是对质量有影响的。
			if (!numFlag && !softenFactorFlag && !qualityFlag) {
				ByteArrayOutputStream out = new ByteArrayOutputStream();
				ImageIO.write(bimage, suffix, out);
				return out.toByteArray();
			}

			// 软化
			if (softenFactorFlag) {
				float[] softenArray = {0, softenFactor, 0, softenFactor,
						1 - (softenFactor * 4), softenFactor, 0, softenFactor, 0};
				Kernel kernel = new Kernel(3, 3, softenArray);
				ConvolveOp cOp = new ConvolveOp(kernel, ConvolveOp.EDGE_NO_OP, null);
				bimage = cOp.filter(bimage, null);
			}

			if (suffixFlag && qualityFlag) {
				//质量压缩
				return quality(bimage, quality, suffix, target);
			} else {
				ByteArrayOutputStream out = new ByteArrayOutputStream();
				ImageIO.write(bimage, suffix, out);
				return out.toByteArray();
			}

		} catch (MalformedURLException e) {
			e.printStackTrace();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		return null;
	}

	/***
	 *
	 * @author zhaosongbin
	 * @date 2020/9/3 16:51
	 * @param image
	 * @param quality
	 * @param suffix
	 * @return byte[]
	 */
	private static byte[] quality(BufferedImage image, float quality, String suffix, String target) {
		try {
			// 得到指定Format图片的writer,得到迭代器
			Iterator iter = ImageIO
					.getImageWritersByFormatName(suffix);
			ImageWriter writer = (ImageWriter) iter.next();

			// 得到指定writer的输出参数设置(ImageWriteParam )
			ImageWriteParam iwp = writer.getDefaultWriteParam();
			// 设置可否压缩
			iwp.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
			// 设置压缩质量参数
			iwp.setCompressionQuality(quality);

			iwp.setProgressiveMode(ImageWriteParam.MODE_DISABLED);

			ColorModel colorModel = ColorModel.getRGBdefault();
			// 指定压缩时使用的色彩模式
			iwp.setDestinationType(new javax.imageio.ImageTypeSpecifier(colorModel,
					colorModel.createCompatibleSampleModel(16, 16)));

			// 开始打包图片，写入byte[]
			// 取得内存输出流
			ByteArrayOutputStream out = new ByteArrayOutputStream();
			IIOImage iIamge = new IIOImage(image, null, null);

			// 此处因为ImageWriter中用来接收write信息的output要求必须是ImageOutput
			// 通过ImageIo中的静态方法，得到byteArrayOutputStream的ImageOutput
			writer.setOutput(ImageIO
					.createImageOutputStream(out));
			writer.write(null, iIamge, iwp);
			//根据字节流生成图片和原图做下比较，测试完注释
			FileOutputStream fos = new FileOutputStream(target);
			fos.write(out.toByteArray());
			fos.close();
			return out.toByteArray();
		} catch (IOException e) {
			e.printStackTrace();
		}

		return null;
	}

}


